package sweezy.swf.tools.flex
{
	import flash.utils.ByteArray;
	import mx.controls.DataGrid;
	import mx.controls.dataGridClasses.DataGridColumn;
	import mx.events.DataGridEvent;

	public class BinaryView extends DataGrid
	{

		private var _bytes:ByteArray;

		private var _data:Array;

		public function BinaryView()
		{
		}

		override public function set dataProvider(value:Object):void
		{
			var bytes:ByteArray = value as ByteArray;
			if (_bytes === bytes)
			{
				return;
			}

			_bytes = bytes;
			if (_bytes === null)
			{
				_data = null;
				super.dataProvider = null;
				return;
			}

			_data = [];
			for (var i:uint = 0, len:uint = Math.ceil(_bytes.length / 16); i < len; i++)
			{
				_data[i] = new Item(i, _bytes);
			}

			super.dataProvider = _data;
		}

		override protected function createChildren():void
		{
			super.createChildren();

			var columns:Array = [this.columns[0]];

			for (var i:int = 0; i < 16; i++)
			{
				var column:BinaryColumn = new BinaryColumn();
				column.offset = i;
				columns[i + 1] = column;
			}

			columns[17] = this.columns[1];
			this.columns = columns;

			addEventListener(DataGridEvent.ITEM_EDIT_BEGINNING, itemEditBeginningHandler);
		}

		private function itemEditBeginningHandler(e:DataGridEvent):void
		{
			if (e.itemRenderer === null)
			{
				e.preventDefault();
				return;
			}

			var item:Item = e.itemRenderer.data as Item;
			if (item === null)
			{
				e.preventDefault();
				return;
			}

			var column:BinaryColumn = columns[e.columnIndex];
			if (item._index * 16 + column.offset >= _bytes.length)
			{
				e.preventDefault();
				return;
			}
		}
	}
}

import flash.utils.ByteArray;

class Item
{

	private static var _table:Array;

	{
		(function():void
		{
			_table = [];
			for (var i:uint = 0x00; i <= 0xff; i++)
			{
				if (i < 0x10)
				{
					_table[i] = "0" + i.toString(16).toLocaleUpperCase();
				}
				else
				{
					_table[i] = i.toString(16).toLocaleUpperCase();
				}
			}
			_table[0x100] = "";
		})();
	}

	public var _index:uint;

	private var _bytes:ByteArray;

	private var _len:uint;

	public function Item(index:uint, bytes:ByteArray):void
	{
		_index = index;
		_bytes = bytes;
		_len = bytes.length;
	}

	public function get address():String
	{
		return ("00000000" + (_index * 16).toString(16)).substr(-8).toLocaleUpperCase();
	}

	public function get h00():String
	{
		return getByte(0x00);
	}

	public function set h00(value:String):void
	{
		return setByte(0x00, value);
	}

	public function get h01():String
	{
		return getByte(0x01);
	}

	public function set h01(value:String):void
	{
		return setByte(0x01, value);
	}

	public function get h02():String
	{
		return getByte(0x02);
	}

	public function set h02(value:String):void
	{
		return setByte(0x02, value);
	}

	public function get h03():String
	{
		return getByte(0x03);
	}

	public function set h03(value:String):void
	{
		return setByte(0x03, value);
	}

	public function get h04():String
	{
		return getByte(0x04);
	}

	public function set h04(value:String):void
	{
		return setByte(0x04, value);
	}

	public function get h05():String
	{
		return getByte(0x05);
	}

	public function set h05(value:String):void
	{
		return setByte(0x05, value);
	}

	public function get h06():String
	{
		return getByte(0x06);
	}

	public function set h06(value:String):void
	{
		return setByte(0x06, value);
	}

	public function get h07():String
	{
		return getByte(0x07);
	}

	public function set h07(value:String):void
	{
		return setByte(0x07, value);
	}

	public function get h08():String
	{
		return getByte(0x08);
	}

	public function set h08(value:String):void
	{
		return setByte(0x08, value);
	}

	public function get h09():String
	{
		return getByte(0x09);
	}

	public function set h09(value:String):void
	{
		return setByte(0x09, value);
	}

	public function get h0a():String
	{
		return getByte(0x0a);
	}

	public function set h0a(value:String):void
	{
		return setByte(0x0a, value);
	}

	public function get h0b():String
	{
		return getByte(0x0b);
	}

	public function set h0b(value:String):void
	{
		return setByte(0x0b, value);
	}

	public function get h0c():String
	{
		return getByte(0x0c);
	}

	public function set h0c(value:String):void
	{
		return setByte(0x0c, value);
	}

	public function get h0d():String
	{
		return getByte(0x0d);
	}

	public function set h0d(value:String):void
	{
		return setByte(0x0d, value);
	}

	public function get h0e():String
	{
		return getByte(0x0e);
	}

	public function set h0e(value:String):void
	{
		return setByte(0x0e, value);
	}

	public function get h0f():String
	{
		return getByte(0x0f);
	}

	public function set h0f(value:String):void
	{
		setByte(0x0f, value);
	}

	public function get text():String
	{
		var result:String = "";
		for (var i:uint = _index * 16, len:uint = i + 16; i < len; i++)
		{
			if (i < _len)
			{
				var code:uint = _bytes[i] & 0xff;
				if (code < 0x20)
				{
					result += ".";
				}
				else
				{
					result += String.fromCharCode(code);
				}
			}
			else
			{
				break;
			}
		}

		return result;
	}

	private function getByte(offset:uint):String
	{
		var pos:uint = _index * 16 + offset;
		return _table[(pos >= _len) ? 0x100 : (_bytes[pos] & 0xff)];
	}

	private function setByte(offset:uint, value:String):void
	{
		var pos:uint = _index * 16 + offset;
		if (pos >= _len)
		{
			return;
		}

		_bytes[pos] = parseInt(value, 16) & 0xff;

	}
}
